package com.ny.zmb.openapi.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.mzlion.easyokhttp.HttpClient;
import com.mzlion.easyokhttp.request.TextBodyRequest;
import com.ny.zmb.glxt.entity.PmStore;
import com.ny.zmb.glxt.service.IPmStoreService;
import com.ny.zmb.openapi.constant.PHPConstant;
import com.ny.zmb.openapi.constant.ResultConstant;
import com.ny.zmb.openapi.entity.*;
import com.ny.zmb.openapi.enums.TransactionStatusEnum;
import com.ny.zmb.openapi.service.*;
import com.ny.zmb.openapi.service.impl.PmMerchantServiceImpl;
import com.ny.zmb.openapi.util.AESUtil;
import com.ny.zmb.openapi.util.ByteUtil;
import com.ny.zmb.openapi.ysutil.YsHttpUtil;
import com.ny.zmb.openapi.ysutil.base.EYinShengBase;
import com.ny.zmb.openapi.ysutil.common.ServiceEnum;
import com.ny.zmb.openapi.ysutil.common.YsPayConstant;
import com.ny.zmb.openapi.ysutil.from.WalletRegisterReqCommand;
import com.ny.zmb.openapi.ysutil.from.merchant.MerchantWithdraw;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.el.stream.Stream;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@CrossOrigin
@RequestMapping("notify")
@RestController
@Slf4j
public class NotifyController extends EYinShengBase {

    @Resource
    private YsHttpUtil ysHttpUtil;
    @Resource
    private IPmStoreService storeService;
    @Resource
    private IPmApiLogService pmApiLogService;
    @Resource
    private IPmStoreService pmStoreService;
    @Resource
    private PmRegisterService pmRegisterService;
    @Resource
    private PmRegisterExamineService pmRegisterExamineService;
    @Resource
    private IPmContractService pmContractService;
    @Resource
    private IPmUserWalletService pmUserWalletService;
    @Resource
    private PmMerchantServiceImpl pmMerchantService;
    @Resource
    private PmUserWalletLogService userWalletLogService;
    @Resource
    private PmUserWalletLogService pmUserWalletLogService;

    /**
     * 提现回调
     *
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/test/withdrawNotify", consumes = "application/x-www-form-urlencoded")
    public String withdrawNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        try {
            String jsonObject = request.getParameter("bizResponseJson");
            JSONObject bizResponseJson = JSONObject.parseObject(jsonObject);
            String status = bizResponseJson.getString("state");
            String requestNo = bizResponseJson.getString("requestNo");
            PmApiLog pmApiLog = new PmApiLog("/withdrawNotify", jsonObject);
            pmApiLogService.save(pmApiLog);

            MerchantWithdraw merchantWithdraw = pmMerchantService.getByRequestNo(requestNo);
            TransactionStatusEnum transactionStatusEnum = merchantWithdraw.getTransactionStatus(status);
            merchantWithdraw.setStatus(transactionStatusEnum);
            merchantWithdraw.setReturnData(jsonObject);
            pmMerchantService.updateById(merchantWithdraw);

            JSONObject obj = new JSONObject();
            obj.put("merchantNo", merchantWithdraw.getMerchantNo());

            // 查询现有余额;
            JSONObject result = pmMerchantService.queryBalances(obj);
            BigDecimal totalAmount = result.getBigDecimal("totalAmount") == null ? BigDecimal.ZERO : result.getBigDecimal("totalAmount");

            Long time = System.currentTimeMillis() / 1000;
            // 插入日志

            String memoString = String.format("商户提现(手续费%.2f元)", 1.00);
            PmUserWalletLog build = PmUserWalletLog.builder()
                    .money(bizResponseJson.getBigDecimal("amount").multiply(BigDecimal.valueOf(-1)))
                    .memo(memoString)
                    .tag(3)
                    .moneyType("merchant")
                    .targetId(requestNo)
                    .userId(merchantWithdraw.getUserId().intValue())
                    .beforeMoney(totalAmount.add(bizResponseJson.getBigDecimal("amount")))
                    .afterMoney(totalAmount)
                    .createtime(time.intValue())
                    .build();
            this.userWalletLogService.addMerchantWalletLog(build);

            // 交易成功
            pmApiLog.setReturnObj("success");
            pmApiLogService.saveOrUpdate(pmApiLog);
        } catch (Exception e) {
            e.printStackTrace();
            log.info(e.getMessage());
            return "success";
        }

        return "success";
    }


    /**
     * 进件回调
     *
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/registerNotify", consumes = "application/x-www-form-urlencoded")
    public String registerNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        try {
            String jsonObject = request.getParameter("bizResponseJson");
            JSONObject bizResponseJson = JSONObject.parseObject(jsonObject);
            String status = bizResponseJson.getString("status");
            PmApiLog pmApiLog = new PmApiLog("/registerNotify", jsonObject);
            pmApiLogService.save(pmApiLog);
            if ("01".equals(status)) {
                String notifyType = bizResponseJson.getString("notifyType");
                if ("01".equals(notifyType)) {
                    JSONObject merchantInfo = bizResponseJson.getJSONObject("merchantInfo");
                    String outMerchantNo = merchantInfo.getString("outMerchantNo");
                    String merchantNo = merchantInfo.getString("merchantNo");
                    // 绑定进件商户号
                    pmRegisterService.updateMerchantNoByOutMerchantNo(outMerchantNo, merchantNo);
                    // 绑定校验商户号
                    pmRegisterExamineService.updateMerchantNoByOutMerchantNo(outMerchantNo, merchantNo);
                    // 绑定店铺商户号
                    pmStoreService.updateMerchantNoByOutMerchantNo(outMerchantNo, merchantNo);
                    // 签约处理合同
                    // todo 异步执行验签
                    pmRegisterService.registerSuccess(merchantInfo);
                }
            }
            pmApiLog.setReturnObj("success");
            pmApiLogService.saveOrUpdate(pmApiLog);
            return "success";
        } catch (Exception e) {
            return "success";
        }
    }

    /**
     * 合同签约回调
     *
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/contractSignNotify", consumes = "application/x-www-form-urlencoded")
    public String contractSignNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        try {
            String bizResponseJsonText = request.getParameter("bizResponseJson");
            // 日志
            pmApiLogService.save(new PmApiLog("/contractSignNotify", bizResponseJsonText));
            JSONObject bizResponseJson = JSONObject.parseObject(bizResponseJsonText);
            bizResponseJson.put("subMsg", "此为合同签约回调");
            pmContractService.save(new PmContract().update(bizResponseJson));
            bizResponseJson.remove("subMsg");
            String requestNo = bizResponseJson.getString("requestNo");
            String merchantNo = bizResponseJson.getString("merchantNo");
            String contractSn = bizResponseJson.getString("contractSn");
            String createTime = bizResponseJson.getString("createTime");
            String state = bizResponseJson.getString("state");
            if ("SUCCESS".equals(state)) {
                // 更新资料
                pmRegisterExamineService.UpdateBymMerchantNo(bizResponseJson);
                //TODO 创建钱包
                try {
                    createWallet(merchantNo);
                } catch (Exception var) {
                    return "success";
                }
            }
            return "success";
        } catch (Exception e) {
            return "success";
        }
    }

    /**
     * 创建钱包
     *
     * @param merchantNo
     */
    private void createWallet(String merchantNo) {
        LambdaQueryWrapper<PmStore> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(PmStore::getBusinessNo, merchantNo);
        PmStore one = this.storeService.getOne(wrapper);
        LambdaQueryWrapper<PmRegister> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(PmRegister::getMerchantNo, merchantNo);
        PmRegister register = this.pmRegisterService.getOne(queryWrapper);
        if (null == one || null == register) {
            return;
        }
        LambdaQueryWrapper<PmUserWallet> lambdaQuery = Wrappers.lambdaQuery();
        lambdaQuery.eq(PmUserWallet::getUserId, one.getUserId());
        List<PmUserWallet> list = this.pmUserWalletService.list(lambdaQuery);
        if (!list.isEmpty()) {
            return;
        }
        String uuid = UUID.randomUUID().toString().replace("-", "");
        WalletRegisterReqCommand command = new WalletRegisterReqCommand();
        command.setCertType("01");
        command.setRequestNo(uuid);
        command.setName(register.getLawyerName());
        command.setMobile(register.getLawyerPhone());
        command.setCertNo(register.getLawyerId());
        JSONObject send = ysHttpUtil.send(ServiceEnum.WALLET_REGISTER, YsPayConstant.ENV_PRD,
                MERCHANT_PRX, MERCHANT_PRX_PWD, ServiceEnum.WALLET_REGISTER.getApiName(), command);
        JSONObject result = send.getJSONObject("bizResponseJson");
        String subCode = result.getString("subCode");
        if (ResultConstant.subCode.equals(subCode)) {
            Long now = System.currentTimeMillis() / 1000;
            PmUserWallet wallet = PmUserWallet.builder().createTime(now.intValue()).userId(one.getUserId()).walletNo(result.getString("merchantNo")).build();
            this.pmUserWalletService.save(wallet);
        }
    }

    /**
     * 封装回调
     *
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping("/divisionRegisterNotify")
    public String divisionRegisterNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String timeStamp = request.getParameter("timeStamp");
        String src = request.getParameter("src");
        String reqId = request.getParameter("reqId");
        String charset = request.getParameter("charset");
        String sign = request.getParameter("sign");
        String bizContent = request.getParameter("bizContent");
        System.out.println(timeStamp);
        System.out.println(src);
        System.out.println(reqId);
        System.out.println(charset);
        System.out.println(sign);
        System.out.println(bizContent);
        if (StringUtils.isNotBlank(bizContent) && StringUtils.isNotBlank(sign)) {
            byte[] data_ = Base64.decodeBase64(bizContent);
            byte[] decrypt = AESUtil.decrypt(data_, ByteUtil.hexStringToBytes(sign));
            String s = new String(decrypt, charset);
            HttpClient.textBody(PHPConstant.BASE_URL + "/api/index/divisionNotify").json(JSONObject.parseObject(s)).execute().asString();

            return "success";
        }
        return "解析失败";
    }

    /**
     * 封装回调 - 进件
     *
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping("/smscNotify")
    public String smscNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        TextBodyRequest textBodyRequest = HttpClient.textBody(PHPConstant.BASE_URL + "/api/index/smscNotify");
        String timeStamp = request.getParameter("timeStamp");
        String src = request.getParameter("src");
        String reqId = request.getParameter("reqId");
        String charset = request.getParameter("charset");
        String sign = request.getParameter("sign");
        String bizContent = request.getParameter("bizContent");
        if (StringUtils.isNotBlank(bizContent) && StringUtils.isNotBlank(sign)) {
            byte[] data_ = Base64.decodeBase64(bizContent);
            byte[] decrypt = AESUtil.decrypt(data_, ByteUtil.hexStringToBytes(sign));
            String s = new String(decrypt, charset);
            JSONObject result = JSONObject.parseObject(s);
            Integer notifyType = result.getInteger("notifyType");
            if (notifyType == 1) {
                LambdaQueryWrapper<PmStore> wrapper = Wrappers.lambdaQuery();
                wrapper.eq(PmStore::getSysFlowId, result.getString("sysFlowId"));
                PmStore one = this.storeService.getOne(wrapper);
                result.put("store", one);
                textBodyRequest.json(result).execute().asString();
            }
            if (notifyType == 2) {

            }
            if (notifyType == 3) {

            }
            if (notifyType == 4) {

            }
            if (notifyType == 5) {

            }
            if (notifyType == 6) {

            }
            return "success";
        }
        return "解析失败";
    }


    /**
     * 封装回调-退款
     *
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping("/refundNotify")
    public String refundNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String timeStamp = request.getParameter("timeStamp");
        String src = request.getParameter("src");
        String reqId = request.getParameter("reqId");
        String charset = request.getParameter("charset");
        String sign = request.getParameter("sign");
        String bizContent = request.getParameter("bizContent");
        if (StringUtils.isNotBlank(bizContent) && StringUtils.isNotBlank(sign)) {
            byte[] data_ = Base64.decodeBase64(bizContent);
            byte[] decrypt = AESUtil.decrypt(data_, ByteUtil.hexStringToBytes(sign));
            String s = new String(decrypt, charset);
            HttpClient.textBody(PHPConstant.BASE_URL + "/api/index/wxRefundNotify").json(JSONObject.parseObject(s)).execute().asString();
            return "success";
        }
        return "解析失败";
    }
}
